bookwiz.io / app / api / books / [id] / route.ts
route.ts
Raw
import { createClient } from '@supabase/supabase-js'
import { NextResponse } from 'next/server'

// Create server-side Supabase client with service role for admin operations
function createServerSupabaseClient() {
  const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY
  if (!serviceRoleKey) {
    throw new Error('SUPABASE_SERVICE_ROLE_KEY is not set')
  }
  
  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    serviceRoleKey,
    {
      auth: {
        autoRefreshToken: false,
        persistSession: false
      }
    }
  )
}

// GET /api/books/[id] - Get a specific book
export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  try {
    const bookId = params.id
    const url = new URL(request.url)
    const userId = url.searchParams.get('userId')

    if (!userId) {
      return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
    }

    const supabase = createServerSupabaseClient()

    const { data: book, error } = await supabase
      .from('books')
      .select(`
        id,
        title,
        description,
        status,
        word_count,
        created_at,
        updated_at,
        author,
        genre,
        target_word_count,
        cover_image_url
      `)
      .eq('id', bookId)
      .eq('user_id', userId)
      .single()

    if (error) {
      console.error('Error fetching book:', error)
      return NextResponse.json({ error: 'Book not found' }, { status: 404 })
    }

    const transformedBook = {
      ...book,
      lastModified: book.updated_at.split('T')[0],
    }

    return NextResponse.json({ book: transformedBook })
  } catch (error) {
    console.error('Unexpected error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}

// PUT /api/books/[id] - Update a specific book
export async function PUT(
  request: Request,
  { params }: { params: { id: string } }
) {
  try {
    const bookId = params.id
    const body = await request.json()
    
    if (!body.userId) {
      return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
    }

    if (!body.title || body.title.trim() === '') {
      return NextResponse.json({ error: 'Title is required' }, { status: 400 })
    }

    const supabase = createServerSupabaseClient()

    // Handle genres - convert array to comma-separated string or use string directly
    const genreValue = Array.isArray(body.genres) && body.genres.length > 0 
      ? body.genres.join(', ') 
      : body.genre?.trim() || null

    const { data: book, error } = await supabase
      .from('books')
      .update({
        title: body.title.trim(),
        description: body.description?.trim() || null,
        author: body.author?.trim() || null,
        genre: genreValue,
        target_word_count: body.target_word_count || null,
        status: body.status || undefined,
        cover_image_url: body.cover_image_url || undefined,
        updated_at: new Date().toISOString()
      })
      .eq('id', bookId)
      .eq('user_id', body.userId)
      .select()
      .single()

    if (error) {
      console.error('Error updating book:', error)
      return NextResponse.json({ error: 'Failed to update book' }, { status: 500 })
    }

    const transformedBook = {
      ...book,
      lastModified: book.updated_at.split('T')[0],
    }

    return NextResponse.json({ book: transformedBook })
  } catch (error) {
    console.error('Unexpected error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}

// DELETE /api/books/[id] - Delete a specific book
export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
) {
  try {
    const bookId = params.id
    const url = new URL(request.url)
    const userId = url.searchParams.get('userId')

    if (!userId) {
      return NextResponse.json({ error: 'User ID is required' }, { status: 400 })
    }

    const supabase = createServerSupabaseClient()

    // First, delete all book files and folders
    const { error: filesError } = await supabase
      .from('file_system_items')
      .delete()
      .eq('book_id', bookId)

    if (filesError) {
      console.error('Error deleting book files:', filesError)
      return NextResponse.json({ error: 'Failed to delete book files' }, { status: 500 })
    }

    // Then delete the book itself
    const { error: bookError } = await supabase
      .from('books')
      .delete()
      .eq('id', bookId)
      .eq('user_id', userId)

    if (bookError) {
      console.error('Error deleting book:', bookError)
      return NextResponse.json({ error: 'Failed to delete book' }, { status: 500 })
    }

    return NextResponse.json({ message: 'Book deleted successfully' })
  } catch (error) {
    console.error('Unexpected error:', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}